package great.project.common.oss2;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * <div  style="border:2px solid red;margin:20px;padding:15px;font-size:24px;text-align:center;color:green;">
 * <p>
 *  OssHelper2 构建类，简化oss客户端的创建
 *
 *  </div>
 *
 * @author zhangshun
 * @date 2020/9/25 20:07
 */
public class OssHelper2Builder {

    private final OSS oss;

    private final OssConfiguration appConfig;

    private final boolean isAutoShutdown;

    public OssHelper2Builder(OssConfiguration appConfig, boolean isAutoShutdown) {
        this.isAutoShutdown = isAutoShutdown;
        this.appConfig = appConfig;
        this.oss = new OSSClientBuilder()
                .build(
                        appConfig.getOssEndPoint(),
                        appConfig.getOssAccessKeyId(),
                        appConfig.getOssAccessKeySecret()
                );
    }


    /**
     * 关闭OSSClient
     */
    public void shutdown() {
        this.oss.shutdown();
    }


    /**
     * 获取 oss 中的 所有的文件列表.
     *
     * @return 结果
     */
    public List<Map<String, Object>> getFileList() {
        ObjectListing objectListing = oss.listObjects(appConfig.getOssBucketName());
        List<Map<String, Object>> result = new ArrayList<>();
        List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
        for (OSSObjectSummary sum : sums) {
            Map<String, Object> map = new HashMap<>();
            map.put("bucket_name", sum.getBucketName());
            map.put("key", sum.getKey());
            map.put("time", sum.getLastModified());
            map.put("size", sum.getSize());
            result.add(map);
        }

        if (isAutoShutdown) {
            shutdown();
        }

        return result;
    }

    /**
     * 指定文件 是否存在
     *
     * @param key 文件的 oss key.
     * @return 结果
     */
    public boolean exist(String key) {
        if (StringUtils.isEmpty(key)) {
            return false;
        }
        if (!oss.doesObjectExist(appConfig.getOssBucketName(), key)) {
            shutdown();
            return false;
        }
        return true;
    }

    public String uploadFile(String key, MultipartFile file, ProgressCallback callback) throws IOException {
        // 如果 key 值不传 默认生成
        if (StringUtils.isEmpty(key)) {
            key = OssHelper2.randomName(file.getName());
        }
        // 上传进度监听
        PutObjectProgressListener listener = new PutObjectProgressListener(file, callback);
        // 文件的 类型
        String contentType = getContentType(Objects.requireNonNull(file.getOriginalFilename()));

        return uploadFile(key, contentType, file.getInputStream(), listener);
    }

    public String uploadFile(String key, File file, ProgressCallback callback) throws IOException {
        // 如果 key 值不传 默认生成
        if (StringUtils.isEmpty(key)) {
            key = OssHelper2.randomName(file.getName());
        }
        // 上传进度监听
        PutObjectProgressListener listener = new PutObjectProgressListener(file, callback);
        // 文件的 类型
        String contentType = getContentType(Objects.requireNonNull(file.getName()));

        return uploadFile(key, contentType, new FileInputStream(file), listener);
    }


    /**
     * 上传文件
     *
     * @param key 文件的 oss key.
     * @return 上传成功 则返回 key ， 如果失败 则返回 null.
     */
    public String uploadFile(String key, String contentType, InputStream fileInputStream, PutObjectProgressListener listener) {

        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(contentType);
        oss.putObject(
                new PutObjectRequest(
                        appConfig.getOssBucketName(),
                        key,
                        fileInputStream,
                        metadata
                )
                        .withProgressListener(listener)
        );
        boolean result = false;
        if (listener.isSucceed()) {
            result = true;
        }
        // 是否自动关闭.
        if (isAutoShutdown) {
            shutdown();
        }
        // 如果成功 返回 key. 失败则不返回.
        if (result) {
            return key;
        }
        return null;
    }


    /**
     * 获取文件的类型
     *
     * @param fileName 文件名字
     * @return 结果
     */
    private String getContentType(String fileName) {
        String[] strArray = fileName.split("\\.");
        final int length = strArray.length;

        if (length < 2){
            throw new RuntimeException("请传入一个完整的文件名字(带后缀的那种)");
        }

        int suffixIndex = strArray.length - 1;
        String suffix = strArray[suffixIndex];
        return MediaType.getContentType(suffix);
    }


}
